<?php

namespace july\julyadmin\builder;

use july\julyadmin\builder\forms;

/**
 * 表单
 */
class Form
{
    //表单数据
    public $data = [];
    //表单请求方式
    public $method = 'post';
    //是否是编辑
    public $isEdit = 0;
    //表单元素
    public $forms = [];
    //tabs
    public $tabs = [];
    //是否是详情
    public $isView = false;
    //是否显示底部按钮
    public $showFooterBtns = true;
    //builder
    private $builder;
    //主键
    public $pk = 'id';
    //表单列数
    private $colWidth = 10;
    //表单label宽度
    private $labelWidth = 3;
    //设置组件部分宽度
    private $inputWidth = 9;
    //表单标题
    private $formTitle = '';
    //表单script
    private $script = '';
    //自定义script脚本
    private $customer_script = '';
    //所有组件html
    private $html = '';
    //所有组件js文件
    private $js = '';
    //所有组件css文件
    private $css = '';
    //自定义style样式
    private $customer_style = '';

    public function __construct($builder, $formTitle = '')
    {
        $this->builder   = $builder;
        $this->formTitle = $formTitle;
    }

    /**
     * 添加文组件
     * @param  string $field          字段
     * @param  string $label          名称
     * @return form
     */
    public function show($type = 'text', $field = '', $label = '')
    {
        switch ($type) {
            //文本组件
            case "text":
                $form = new forms\Text($field, $label);
                break;
            //number组件
            case "number":
                $form = new forms\Number($field, $label);
                break;
            //年月日组件
            case "date":
                $form = new forms\Date($field, $label);
                break;
            //文本域组件
            case "textarea":
                $form = new forms\Textarea($field, $label);
                break;
            //年月日时分秒组件
            case "datetime-local":
                $form = new forms\DatetimeLocal($field, $label);
                break;
            //年月日组件
            case "month":
                $form = new forms\Month($field, $label);
                break;
            //时分组件
            case "time":
                $form = new forms\Time($field, $label);
                break;
            //周组件
            case "week":
                $form = new forms\Week($field, $label);
                break;
            //颜色选择组件
            case "color":
                $form = new forms\Color($field, $label);
                break;
            //邮箱组件
            case "email":
                $form = new forms\Email($field, $label);
                break;
            //下拉组件
            case "select":
                $form = new forms\Select($field, $label);
                break;
            //开关组件
            case "switchBtn":
                $form = new forms\SwitchBtn($field, $label);
                break;
            //复选框组件
            case "checkbox":
                $form = new forms\Checkbox($field, $label);
                break;
            //单选框组件
            case "radio":
                $form = new forms\Radio($field, $label);
                break;
            //密码组件
            case "password":
                $form = new forms\Password($field, $label);
                break;
            //ueditor编辑器组件
            case "ueditor":
                $form = new forms\Ueditor($field, $label);
                break;
            //html文本组件
            case "html":
                $form = new forms\Html($field, $label);
                break;
            //图标选择组件
            case "iconPicker":
                $form = new forms\IconPicker($field, $label);
                break;
            //tags组件
            case "tags":
                $form = new forms\Tags($field, $label);
                break;
            //jstree
            case "jsTree":
                $form = new forms\JsTree($field, $label);
                break;
            //image上传
            case "image":
                $form = new forms\Image($field, $label);
                break;
            //file上传
            case "file":
                $form = new forms\File($field, $label);
                break;
            //items
            case "items":
                $form = new forms\Items($field, $label);
                break;
            //hidden组件
            case "hidden":
                $form = new forms\Hidden($field, $label);
                break;
            //高德地图组件
            case "gaodeMap":
                $form = new forms\GaodeMap($field, $label);
                break;
            //editor-md组件
            case "editorMd":
                $form = new forms\EditorMd($field, $label);
                break;
            default:
                throw new \Exception("{$type}组件不存在！");
                break;

        }
        if ($this->isView) {
            $form->isView(true);
        }
        $form->setData($this->data);
        $form->setIsEdit($this->isEdit);
        $form->setColWidth($this->colWidth);
        $form->size($this->labelWidth, $this->inputWidth);
        $this->forms[] = $form;
        return $this->forms[count($this->forms) - 1];
    }

    /**
     * tabs
     * @param  string  $tab_id tabid
     * @return tabs
     */
    public function tabs($tab_id)
    {
        $tab           = new forms\Tabs($tab_id);
        $this->forms[] = $tab;
        return $this->forms[count($this->forms) - 1];
    }

    /**
     * tab开始
     * @return this
     */
    public function tabStart()
    {
        $html = <<<EOT

            <div class="tab-content">

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * tab开始输入
     * @param  string $tab_item_id tab选项卡id
     * @return this
     */
    public function tabItemStart($tab_item_id)
    {
        if (!$tab_item_id) {
            throw new \Exception("tab_item_id不能为空！");
        }

        $html = <<<EOT

            <div class="tab-pane fade row" id="tabs_{$tab_item_id}">

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * tab选项卡结束输入
     * @return this
     */
    public function tabItemEnd()
    {
        $html = <<<EOT
            <div class="tab-item-end"></div>
            </div>
EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * tab结束
     * @return this
     */
    public function tabEnd()
    {
        if (!isset($this->forms[count($this->forms) - 1]['html']) || stripos($this->forms[count($this->forms) - 1]['html'], 'tab-item-end') == -1) {
            throw new \Exception("tabEnd()的上一个方法必须是tabItemEnd()！");
        }
        $html = <<<EOT

        </div>

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * 设置表单列宽
     * @param  integer $colWidth 列宽
     * @return this
     */
    public function setColWidth($colWidth = 12)
    {
        if ($this->forms) {
            $this->forms[count($this->forms) - 1]->setColWidth($colWidth);
            return $this->forms[count($this->forms) - 1];
        } else {
            $this->colWidth = $colWidth;
            return $this;
        }

    }

    /**
     * 设置form表单label和input宽度
     * @Author   July
     * @DateTime 2024-01-24T21:21:34+0800
     * @param    integer                   $labelWidth label宽度，1-12
     * @param    integer                   $inputWidth input宽度，1-12
     * @return   this
     */
    public function size($labelWidth, $inputWidth)
    {
        if ($this->forms) {
            $this->forms[count($this->forms) - 1]->size($labelWidth, $inputWidth);
            return $this->forms[count($this->forms) - 1];
        } else {
            $this->labelWidth = $labelWidth;
            $this->inputWidth = $inputWidth;
            return $this;
        }
    }

    /**
     * 左边开始
     * @param  integer $width 宽度1-12
     * @return this
     */
    public function leftStart($width = 6)
    {
        $html = <<<EOT

                <div class="col-{$width}" style="float:left;">

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * 左边结束
     * @Author   july
     * @DateTime 2023-09-07
     * @return   this
     */
    public function leftEnd()
    {
        $html = <<<EOT

        </div>

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * 右边开始
     * @param  integer $width 宽度1-12
     * @return this
     */
    public function rightStart($width = 6)
    {
        $html = <<<EOT

                <div class="col-{$width}" style="float:right;">

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * 右边结束
     * @Author   july
     * @DateTime 2023-09-07
     * @return   this
     */
    public function rightEnd()
    {
        $html = <<<EOT

        </div>

EOT;
        $this->forms[] = [
            'html'   => $html,
            'script' => '',
        ];
        return $this;
    }

    /**
     * 表单加入js
     * @Author   July
     * @DateTime 2023-10-23T17:17:13+0800
     * @param    string                   $script script代码
     * @return   this
     */
    public function script($script = '')
    {
        $this->customer_script = $script;
        return $this;
    }

    /**
     * 表单加入样式
     * @Author   July
     * @DateTime 2023-10-23T17:56:08+0800
     * @param    string                   $style 样式
     * @return   this
     */
    public function style($style = '')
    {
        $this->customer_style = $style;
        return $this;
    }

    /**
     * 是否显示表单底部按钮
     * @Author   July
     * @DateTime 2024-01-24T21:02:52+0800
     * @param    boolean                  $show 是否显示，true|false
     * @return   this
     */
    public function showFooterBtns($show = true)
    {
        $this->showFooterBtns = $show;
        return $this;
    }

    /**
     * 渲染表單
     */
    public function render()
    {
        $get           = input('get.', []);
        $get['isEdit'] = $this->isEdit;
        $action        = url(request()->controller() . "/" . request()->action(), $get);

        $forms = json_encode($this->forms, JSON_UNESCAPED_UNICODE);

        if (!$this->isView) {
            $this->script .= <<<EOT
        <script>
            var window_name = window.name;
            var forms = {$forms};
            //提交表单
            function formSubmit(that){
                formValidate(true);
                if($("#form").valid()){
                    window.loading  = layer.load(2, { shade:  [0.2, '#000'] });
                    //获取没有选中的checkbox，在同级创建要给hidden，设置值为0，不然提交的时候没有这个key
                    $("#form").find("input:checkbox").not("input:checked").each(function(){
                        var name = $(this).attr("name");
                        if($(this).parent().find("input[type='hidden']").length==0 && name.indexOf("[]")<0){
                            $(this).parent().append("<input type='hidden' name='"+name+"' value='0'/>");
                        }
                    });

                    //获取选中的checkbox，把同级的hidden删除
                    $("#form").find('input[type="checkbox"]:checked').each(function(){
                        if($(this).parent().find("input[type='hidden']").length>0 && name.indexOf("[]")<0){
                            $(this).parent().find("input[type='hidden']").remove();
                        }
                    });

                    $.ajax({
                        type:'POST',
                        url:'{$_SERVER['REQUEST_URI']}',
                        data:$("#form").serialize(),
                        dataType:'json',
                        success:function(res) {
                            layer.close(window.loading);
                            if(res.code==1){
                                parent.layer.msg(res.msg,{
                                    icon:6,
                                    time:2000,
                                    shade:[0.6,'#000',false]
                                });
                                if(parent.hasOwnProperty("tableRefresh")){
                                    //当layer.open是默认打开的时候可以调用
                                    parent.tableRefresh();
                                }else{
                                    //当layer.open是用parent.layer.open或者top.layer.open打开的时候上面就找不到方法
                                    //只能用下面获取父页面中的所有iframe,并且找到当前激活的tab里面的iframe，调用这个iframe中的tableRefresh来刷新页面表格
                                    var iframe = $(window.parent.document).find('iframe');
                                    iframe.map(index=>{
                                        if(iframe.eq(index).attr("class")=="tab-pane active"){
                                            var iframe_id = iframe.eq(index).attr("id");
                                            if($(iframe.eq(index))[0].contentWindow.hasOwnProperty("tableRefresh")){
                                                $(iframe.eq(index))[0].contentWindow.tableRefresh()
                                            }else{
                                                window.location.reload();
                                            }
                                        }
                                    })
                                }
                                if(res.hasOwnProperty('url') && res.url){
                                    location.href = res.url;
                                }else{
                                    //关闭父窗口
                                    var index = parent.layer.getFrameIndex(window_name); //先得到当前iframe层的索引
                                    parent.layer.close(index); //再执行关闭
                                }

                            }else{
                                layer.msg(res.hasOwnProperty('msg') && res.msg?res.msg:'操作失败！',{
                                    icon:5,
                                    time:2000,
                                    shade:[0.6,'#000',false]
                                });
                            }
                        },
                        error:function(res){
                            layer.close(window.loading);
                            layer.msg(JSON.stringify(res),{
                                icon:5,
                                time:2000,
                                shade:[0.6,'#000',false]
                            });
                        }
                    });
                }
            }

            //清空表单
            function clearSearchForm(that){
                //清空表单原生控件
                $("#form")[0].reset();
                //清空表单select2控件
                forms.map(item=>{
                    if(item.dataUrl!= '' && item.type=='select'){
                        if(item.multiple==true){
                            //多选取消
                            var select2_id = $("select[name='"+item.field+"[]']").attr("id");
                            var select_data = $("select[name='"+item.field+"[]']").select2("data");
                            if(select_data!= undefined){
                                var ids = [];
                                select_data.map(item=>{
                                    ids.push(item.id);
                                });
                                $("#"+select2_id).val(ids).trigger('change');
                                $("#select2-"+select2_id+"-container").html("");
                            }
                        }else{
                            //单选取消
                            var select2_id = $("select[name='"+item.field+"']").attr("id");
                            $("#"+select2_id).empty();
                        }
                    }
                });
            }
EOT;
        }
        $this->script .= <<<EOT
        </script>

        {$this->customer_script}
EOT;

        $this->html = <<<EOT

            <form id="form" action="{$action}" class="form-row row" method="post" role="form">
EOT;
        foreach ($this->forms as $k => $v) {
            $form = is_array($v) ? $v : $v->render();
            $this->html .= $form['html'];
            $this->script .= $form['script'];
            $this->js .= isset($form['js']) ? $form['js'] : '';
            $this->css .= isset($form['css']) ? $form['css'] : '';
        }

        $this->html .= $this->customer_style;

        //去除掉重复引用的js文件
        $preg = "/<script(.*)+<\/script>/";
        preg_match_all($preg, $this->js, $res);
        if (isset($res[0]) && $res[0]) {
            foreach ($res[0] as $jk => $jv) {
                $count = 0;
                foreach ($res[0] as $jk1 => $jv1) {
                    if ($count <= 1) {
                        if ($jv == $jv1) {
                            $count++;
                        }
                    }
                    if ($count > 1) {
                        unset($res[0][$jk]);
                        continue;
                    }
                }
            }
        }
        $this->js = implode("\n", $res[0]);

        //去除掉重复引用的css文件
        $preg = "/<link(.*)+>/";
        preg_match_all($preg, $this->css, $res);
        if (isset($res[0]) && $res[0]) {
            foreach ($res[0] as $ck => $cv) {
                $count = 0;
                foreach ($res[0] as $ck1 => $cv1) {
                    if ($count <= 1) {
                        if ($cv == $cv1) {
                            $count++;
                        }
                    }
                    if ($count > 1) {
                        unset($res[0][$ck]);
                        continue;
                    }
                }
            }
        }
        $this->css = implode("\n", $res[0]);

        if (!$this->isView && $this->showFooterBtns) {
            $this->html .= <<<EOT
                <div style="text-align:center;" class="form-btns">
                    <button type="button" onclick="formSubmit(this);" style="margin-right:2px;" class="btn btn-primary">提交</button>
                    <button type="button" onclick="clearSearchForm(this)" class="btn btn-warning">重置</button>
                </div>
            </form>
EOT;
        }

        $this->builder->renderTop(true, $this->css . $this->js);
        $content = <<<EOT

        <div class="container-fluid" style="min-height:100%;">
              <div class="card">

EOT;
        if ($this->formTitle) {
            $content .= <<<EOT

            <header class="card-header">
                        <div class="card-title">{$this->formTitle}</div>
                    </header>

EOT;
        }
        $content .= <<<EOT
                    <div class="card-body">
                        <div class="row m-0 p-0">
                            {$this->html}
                        </div>
                    </div>
              </div>
        </div>
EOT;
        echo $content . $this->script;
        $this->builder->renderBottomSource();
        $this->builder->renderBottom();
    }
}
